package com.tuuzed.android.sqlite;

import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import com.tuuzed.android.sqlite.internal.ColumnInfo;
import com.tuuzed.android.sqlite.internal.SQLiteValueConverter;

import java.util.Iterator;
import java.util.List;

/**
 * 游标迭代器
 *
 * @param <T>
 */
public final class CursorIterator<T> implements Iterator<T> {
    private static final String TAG = "CursorIterator";

    private Cursor cursor;
    private Class<T> tableClass;
    private boolean hasNext;
    private List<ColumnInfo> columnInfos;


    static <T> CursorIterator<T> create(@NonNull Cursor cursor,
                                        @NonNull Class<T> tableClass,
                                        @NonNull List<ColumnInfo> columnInfos) {
        return new CursorIterator<>(cursor, tableClass, columnInfos);
    }

    private CursorIterator(@NonNull Cursor cursor,
                           @NonNull Class<T> tableClass,
                           @NonNull List<ColumnInfo> columnInfos) {
        this.cursor = cursor;
        this.tableClass = tableClass;
        this.columnInfos = columnInfos;
        hasNext = cursor.moveToFirst();
    }

    @Override
    public boolean hasNext() {
        return hasNext;
    }

    @Override
    public T next() {
        T t = null;
        while (t == null) {
            try {
                t = processCursor(cursor);
            } catch (Exception e) {
                Log.w(TAG, "next: ", e);
            }
            hasNext = cursor.moveToNext();
            if (!hasNext()) return t;
        }
        return t;
    }

    @Override
    public void remove() {
        cursor.close();
    }

    @Nullable
    private T processCursor(Cursor cursor)
            throws InstantiationException, IllegalAccessException {
        T t = tableClass.newInstance();
        if (t != null) {
            for (ColumnInfo columnInfo : columnInfos) {
                try {
                    SQLiteValueConverter.setFieldValue(columnInfo, t, cursor);
                } catch (Exception e) {
                    Log.w(TAG, "processCursor: ", e);
                }
            }
        }
        return t;
    }
}
